package de.mmis.core.base.device;

import java.util.Map;


/**
 * a Device wraps an Object, that is not accessible all the time. Only if
 * isAvailable() returns true, the object can be accessed and used via getDevice
 * method. Unavailability is limited only to method calls, a device can be
 * observed even if it is currently not available (and thus giving no events)
 * 
 * @author Christian Koch
 * 
 * @param <D>
 *            type of the Object which is wrapped
 */
public interface Device<D> {
	/**
	 * @return the unique ID of this device.
	 */
	public String getID();

	/**
	 * @return the wrapped object. It is guaranteed that getDevice returns the
	 *         same value on every call and never returns <code>null</code>
	 */
	public D getDevice();

	/**
	 * ensures the availability of the device until releaseAvailability will be
	 * called. This call will block until the device is available. <br>
	 * <b>IMPORTANT:</b> do not forget to call releaseAvailability when done.
	 */
	public void ensureAvailability();

	/**
	 * tests if the device is available and, if so, ensures the availability of
	 * the device until releaseAvailability will be called. This call not will
	 * block. <br>
	 * <b>IMPORTANT:</b> do not forget to call releaseAvailability when
	 * <code>true</code> was returned.
	 * 
	 * @return true, if device is available and therefore now locked, otherwise
	 *         false
	 */
	public boolean tryEnsureAvailability();

	/**
	 * releases the availability guarantee given by ensureAvailability or
	 * tryEnsureAvailability methods. Note that for each call of one of these
	 * methods you should call this method once to release the lock properly.
	 */
	public void releaseAvailability();

	/**
	 * @return a mapping of custom properties of this device.
	 */
	public Map<String, Object> getPropertyMap();
}
